/*
 Copyright (C) 2010-2013. 
 Ezequiel Palumbo, Calipsoide FOSS Foundation.
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public License
 along with this program.  If not, see http://www.gnu.org/licenses/. 
 
 Email: contacto@ehpalumbo.com.ar 
*/

package org.calipsoide.dbf2xml.xml;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.calipsoide.dbf2xml.model.Field;
import org.calipsoide.dbf2xml.model.Record;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

/**
 * 
 * Basic implementation of the DOM Builder interface. At this version, it is 
 * not very configurable. Creates a DOM object with a list of nodes 
 * representing records. 
 * 
 * @since 1.0
 * @author ehpalumbo
 *
 */
public class BasicDOMBuilder implements DOMBuilder {

	private static final Log LOGGER = LogFactory.getLog(BasicDOMBuilder.class); 
	
	public static final String RECORDS_TAG_NAME = "records";
	public static final String ROW_TAG_NAME = "record";
	public static final String ID_ATTRIBUTE_NAME = "id";

	public static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd";
	public static final String DOUBLE_FORMAT_PATTERN = "##.##";

	private static final DateFormat DATE_FORMATTER = 
			new SimpleDateFormat(DATE_FORMAT_PATTERN);
	
	private static final NumberFormat NUMBER_FORMATTER = 
			new DecimalFormat(DOUBLE_FORMAT_PATTERN);
			
	public BasicDOMBuilder() {
		super();
	}
	
	protected Log getLogger() {
		return LOGGER;
	}
	
	public DateFormat getDateFormatter() {
		return DATE_FORMATTER;
	}
	
	public static NumberFormat getNumberFormatter() {
		return NUMBER_FORMATTER;
	}
	
	public String getRecordsTagName() {
		return RECORDS_TAG_NAME;
	}

	public String getRowTagName() {
		return ROW_TAG_NAME;
	}
	
	public void build(final Document document,
			final List<Record> records) {
		final Element recordsTag = document.createElement(getRecordsTagName());
		Element rowTag = null;
		Element columnTag = null;
		Text value = null;
		getLogger().debug("Building DOM object with records...");
		int i = 0;
		for (Record record : records) {
			rowTag = document.createElement(getRowTagName());
			final Attr idAttr = document.createAttribute(ID_ATTRIBUTE_NAME);
			idAttr.setValue(record.getId().toString());
			rowTag.setAttributeNode(idAttr);
			for (Field field : record.getFields()) {
				columnTag = document.createElement(
						field.getName().trim().replace(" ","_").toLowerCase());
				value = document.createTextNode(format(field));
				columnTag.appendChild(value);
				rowTag.appendChild(columnTag);
			}
			recordsTag.appendChild(rowTag);
			getLogger().trace(++i + " record added to document.");
		}
		document.appendChild(recordsTag);
		getLogger().debug("Document has been built with "+ i + " records.");
	}

	private String format(final Field field) {
		final Object object = field.getValue();
		String formattedValue = "";
		if (object != null) {
			if (object instanceof Date) {
				formattedValue = getDateFormatter().format((Date)object);
			} else if (object instanceof Double) {
				formattedValue = getNumberFormatter().format((Double)object);
			} else {
				formattedValue = object.toString().trim();
			}
		}
		return formattedValue;
	}

}
